from django.shortcuts import render
from rest_framework import status

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
# Create your views here.

# 问题！！！
# 因为我们已经告知系统 子应用在apps中 不需要再添加apps
# from apps.users.models import Users

# 正确的
from rest_framework_jwt.views import ObtainJSONWebToken

from areas.serializers import AddressTitleSerializer
from goods.models import SKU
from goods.serializers import SKUSerializer
from users.models import Users
from users.utlis import check_verify_token
from .serializers import RegisterCreateUserSerializer, UserHistorySerializer


# APIView       基类
# GenericAPIView     列表视图和详情视图做了通用支持， 配合mixin 比较容易
# ListAPIView         通用支持,省去了 http 的方法
# 判断用户是否存在
class RegisterUsernameView(APIView):
    """
    判断用户名是否存在
    1.让前端把用户名传递过来
    2.以get方式把用户名传递过来
    3.实现业务逻辑

    GET         users/usernames/username/

    GET          /users/usernames/(?P<username>\w{5,20})/count/


    GET         /users/usernames/count/?username=xxxx
    """

    def get(self, request, username):
        # count = 0 没有
        # count = 1 注册过
        count = Users.objects.filter(username=username).count()

        # 组织数据
        context = {
            'count': count,
            'username': username
        }

        return Response(context)


# 如何选取 视图类

# 注册
class RegisterCreateUserView(APIView):
    """
    1.我们需要让前端把 用户名，密码，确认密码，手机号，短信验证码，是否同意协议 传递过来
    2.后端接收参数，对参数进行校验
    3.数据入库
    4.返回响应

    get
    post        post相对于get而言 安全

    POST        /users/

    """

    def post(self, request):
        # 1. 接收参数
        data = request.data
        # 2. 创建序列化器
        serializer = RegisterCreateUserSerializer(data=data)
        # 进行校验
        # raise_exception=True 如果有异常，则抛出异常，后边的代码不执行
        serializer.is_valid(raise_exception=True)

        # 3.数据入库
        serializer.save()

        # Users.objects.create(**validated_data)
        # 如果我们的data没有问题，就相当于下边的写发
        # data = {'username':xxx,'password2':xxx}
        # data 多余的字段删除掉
        # Users.objects.create(**data)

        # 4.返回响应
        # serializer.data 做什么？
        # 将对象转换为字典       序列化操作
        # user --> 字典中 key
        return Response(serializer.data)
# 查询手机号的个数
class RegisterPhoneCountAPIView(APIView):
    """
    查询手机号的个数
    GET: /users/phones/(?P<mobile>1[345789]\d{9})/count/
    """

    def get(self, request, mobile):
        # 通过模型查询获取手机号个数
        count = Users.objects.filter(mobile=mobile).count()
        # 组织数据
        context = {
            'count': count,
            'phone': mobile
        }

        return Response(context)


#####################二级视图####################
from rest_framework.mixins import CreateModelMixin

# 二级视图的写法
class RegisterCreateUser2View(CreateModelMixin, GenericAPIView):
    serializer_class = RegisterCreateUserSerializer

    def post(self, request):
        return self.create(request)


#####################三级视图####################
from rest_framework.generics import CreateAPIView

# 三级视图的写法
class RegisterCreateUser3View(CreateAPIView):
    serializer_class = RegisterCreateUserSerializer


#### 1. 如果我们分析不出来就先继承自APIView
#       实现了功能之后，再对代码进行优化和封装

from rest_framework.permissions import IsAuthenticated
from .serializers import UserInfoSerializer
from rest_framework.mixins import RetrieveModelMixin
# 一级视图
# class UserCenterInfoView(APIView):
#     """
#     1.必须是登录用户才可以访问该页面
#     2.获取用户信息， 直接返回就可以
#
#     get  /users/infos/
#
#     """
#     #必须是登录用户才可以访问该页面
#     permission_classes = [IsAuthenticated]
#
#     def get(self,request):
#
#         #我们是采用的jwt token认证
#         #前段把 token传递给我 我就知道谁登录
#         # requst.user 就是 认证登录的用户
#
#         user = request.user
#
#         serializer = UserInfoSerializer(user)
#
#         return Response(serializer.data)


from rest_framework.generics import GenericAPIView
from rest_framework.mixins import RetrieveModelMixin
# 二级视图
# class UserCenterInfoView(RetrieveModelMixin,GenericAPIView):
#     """
#     1.必须是登录用户才可以访问该页面
#     2.获取用户信息， 直接返回就可以
#
#     get  /users/infos/
#
#     """
#     #必须是登录用户才可以访问该页面
#     permission_classes = [IsAuthenticated]
#
#     serializer_class = UserInfoSerializer
#
#     # queryset = Users.objects.all()
#
#     def get_object(self):
#
#         return self.request.user
#
#     def get(self,request):
#
#         return self.retrieve(request)

from rest_framework.generics import RetrieveAPIView

# 用户必须登陆才可以访问该页面
class UserCenterInfoView(RetrieveAPIView):
    """
        1.必须是登录用户才可以访问该页面
        2.获取用户信息， 直接返回就可以

        get  /users/infos/

        """
    # 必须是登录用户才可以访问该页面
    permission_classes = [IsAuthenticated]

    serializer_class = UserInfoSerializer

    # queryset = Users.objects.all()

    def get_object(self):
        return self.request.user


from rest_framework.generics import UpdateAPIView
from .serializers import EmailSerializer
from rest_framework.mixins import UpdateModelMixin
# # 用户中心界面 中邮箱的设置    视图视图
# class UserUpdateEmailView(APIView):
#     """
#     1.用户在点击设置的时候，输入邮箱，点击保存的时候，前段应该将 邮件信息发送给后台
#     # 2. 后台接受到 邮件信息之后 需要进行校验，
#     # 3.校验完成之后对数据进行 保存操作
#     # 4. 保存之后要发送一封激活邮件
#     # 5. 返回响应
#
#     PUT     /users/emails/
#
#     """
#
#     permission_classes = [IsAuthenticated]
#
#     def put(self, request):
#         # 1. 后台接受到 邮件信息之后 需要进行校验，
#         user = request.user
#
#         data = request.data
#
#         serializer = EmailSerializer(instance=user, data=data)
#
#         serializer.is_valid(raise_exception=True)
#
#         # .2校验完成之后对数据进行 保存操作
#         serializer.save()
#
#         # 3.返回响应
#         return Response(serializer.data)

from rest_framework import status
#
# 发送邮件   的三级视图
class UserUpdateEmailView(UpdateAPIView):

    permission_classes = [IsAuthenticated]
    serializer_class = EmailSerializer

    def get_object(self):

        return self.request.user



class UserEmailActiveView(APIView):

    """

    GET         users/emails/verifications/?token=xxxx
    """

    def get(self, request):

        # 1. 获取token
        token = request.query_params.get('token')
        if token is None:
            return Response({'msg': '缺少参数'}, status=status.HTTP_400_BAD_REQUEST)
        # 2.对token进行处理 {Id：xxx,email:xxx}
        id = check_verify_token(token)

        if id is None:
            return Response({'msg': 'token过期了'}, status=status.HTTP_400_BAD_REQUEST)

        # 3.根据id查询用户
        try:
            user = Users.objects.get(id=id)
        except Users.DoesNotExist:
            return Response({'msg': '没有此用户'}, status=status.HTTP_400_BAD_REQUEST)

        # 4.修改状态，返回响应
        user.email_active = True
        user.save()

        return Response({'msg': 'ok'})



#
# # 邮箱的相关配置  mall  中setting
# # 使用三级视图需要考虑   在序列化器中发送短息   激活  的位置
# from rest_framework.generics import UpdateAPIView
#
# class UserUpdateEmailView(UpdateAPIView):
#
#     permission_classes = [IsAuthenticated]
#     serializer_class = EmailSerializer
#
#     def get_object(self):
#
#         return self.request.user
from .serializers import AddressSerializer


# 添加收货地址
class AddressView(APIView):
    # pagination_class = None

    """
    POST        users/addresses/
    """

    permission_classes = [IsAuthenticated]

    def post(self,request):
        """
        1.前端收集用户提交的数据，传递给后端
        2. 接受数据，并对数据进行校验
        3. 数据没有问题就入库
        4. 返回响应

        """

        data = request.data

        serializer = AddressSerializer(data=data,context={'request':request})

        serializer.is_valid(raise_exception=True)

        serializer.save()

        return Response(serializer.data)

# 地址列表

class AddressCreateAPIView(APIView):
    """用户新增地址"""

    # POST  /users/addresses/


    permission_classes = [IsAuthenticated]

    def post(self, request):
        data = request.data
        serializer = AddressSerializer(data=data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

# class AddressListAPIView(APIView):
    """获取用户地址列表"""

    # GET  /users/addresses/

    # permission_classes = [IsAuthenticated]

    def get(self, request):
        addresses = Address.objects.all()
        serializer = AddressSerializer(addresses, many=True)
        user = request.user
        return Response({
            'user_id': user.id,
            'default_address_id': user.default_address_id,
            'limit': 20,
            'addresses': serializer.data
        })
from .models import Address
class AddressDeleteAPIView(APIView):
    """删除用户地址"""

    def delete(self, request, pk):
        address = Address.objects.get(pk=pk)
        address.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class AddressUpdateAPIView(APIView):
    """修改用户地址"""

    def put(self, request, pk):
        # 获取模型信息  的用户
        address = Address.objects.get(pk=pk)
        # 获取前端数据
        data = request.data
        # 进行序列化
        serializer = AddressSerializer(address, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

class AddressTitleAPIView(APIView):
    """修改地址标题"""
    def put(self, request, pk):
        address = Address.objects.get(pk=pk)
        data = request.data
        serializer = AddressTitleSerializer(address, data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

class AddressDefaultAddressAPIView(APIView):
    """设置默认地址"""

    def put(self, request, pk):
        address = Address.objects.get(pk=pk)
        request.user.default_address = address
        request.user.save()
        return Response({'message': 'OK'}, status=status.HTTP_200_OK)







                # 1.根据 原型图 尽量多的分析出字段， 比较明显的表可以区分出来
    #尽量不要分析表和表之间的关系


#2. 最后 找一个安静的 时间 没有人打扰的时间 去分析表和表之间的关系（一个表和一个表之间分析）


# 多对多的时候
#  多对多转换为3个表
# 转换为 2个 1：n 和 m；1

#供应商 和 商品


# 1个供应商可能供应多个商品
# 1富士康  华为手机，苹果手机

# 1个商品被多个供应商供应
# 1个华为手机    富士康，付土康


# 供应商
# 供应商_id, 供应商_name
#   1           富士康
#   2           付土康

# 产品
# 产品_id ,产品_name
#   1         iphone
#   2       huawei


# 第三个表
# 供应商_id, 产品的_id
#   1       1
#   1       2
#   2       1
#   2       2


# 一下是实现新功能的东西
#  需要用户登录的

# 1. 在详情页面，我们需要让前端将 商品id，和用户信息传递给后台， 这样的话 才可以保存浏览记录

# 2. 展示浏览记录的时候，根据用户的id信息，查询指定的数据
#       数据的保存是可以保存在 数据库中的，但是我们的知识点设计的是 保存在Redis
#  二级视图才有分页功能
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin
from django_redis import get_redis_connection
class UserHistoryView(APIView):

    """
    1.实现用户浏览数据的入库操作
     1.1 让前端把 商品id，用户信息 发送给后端
     # 1.2 后端接受数据，并且对数据进行校验
     # 1.3 校验没有问题，数据入库（Redis）
     # 1.4 返回响应

    POST    /users/browerhistories/
    """

    permission_classes = [IsAuthenticated]
    # 我们是采用的jwt的认证方法，所以 需要让前端把token 传递过来
    # token是放在请求的header中

    # 商品id放在body中就可以


    def post(self,request):
        # 1.2 后端接受数据，并且对数据进行校验
        data = request.data

        serializer = UserHistorySerializer(data=data)
        serializer.is_valid()    # 调用序列化校验
        sku_id = serializer.data.get('sku_id')
        # 1.3 校验没有问题，数据入库（Redis）

        # 1.3.1连接redis
        redis_conn = get_redis_connection('history')
         #  在这里有个小八个，数据的增多  解决方法
        # 1.3.2 把数据保存到redis中lrem  count=0移除表中所有与value相等的值
        # 先删除可能存在的 sku_id  删除所有  >0 移除表头到表尾搜索的值
        redis_conn.lrem('history_%s' % request.user.id, 0, sku_id)
        # 再添加
        redis_conn.lpush('history_%s'%request.user.id,sku_id)

        #。1.3.3 只保留5个
        redis_conn.ltrim('history_%s'%request.user.id,0,4)


        # 1.4 返回响应
        return Response(serializer.data)


    def get(self,request):

        #1. 连接redis

        redis_conn = get_redis_connection('history')
        #2. 获取浏览记录 [1,2,3]
        ids = redis_conn.lrange('history_%s'%request.user.id,0,5)

        # 3.根据id获取详细信息 [SKU,SKU,SKU]
        # sku_ids = SKU.objects.filter(pk__in=ids)
        # 如果采用in进行查询，我们的顺序就错乱了  ids  什么字段
        skus = []
        for sku_id in ids:

            sku = SKU.objects.get(pk=sku_id)

            skus.append(sku)

        # 4.将 对象列表进行序列化器的操作
        serialzier = SKUSerializer(skus,many=True)
        # 5.返回响应
        return  Response(serialzier.data)



from cart.utils import merge_cookie_to_redis

class UserAuthorizationView(ObtainJSONWebToken):

    def post(self, request):
        # 调用jwt扩展的方法，对用户登录的数据进行验证
        response = super().post(request)

        # 如果用户登录成功，进行购物车数据合并
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            # 表示用户登录成功
            user = serializer.validated_data.get("user")
            # 合并购物车
            #merge_cart_cookie_to_redis(request, user, response)
            response = merge_cookie_to_redis(request, user, response)

        return response





